/*
 * 
 *  This file is part of Sourceprojects.org Lycia Copyright 2010 noctarius
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * 
 */
package org.sourceprojects.lycia.internal.io;

import java.io.IOException;
import java.io.LineNumberReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.sourceprojects.lycia.LyciaParser;
import org.sourceprojects.lycia.exceptions.LyciaParsingException;
import org.sourceprojects.lycia.internal.logging.LyciaLoggerWrapper;
import org.sourceprojects.lycia.io.LyciaReader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;

public class VisualAgeRPGTextReader<B> implements LyciaReader<B> {
	private static final LyciaLoggerWrapper LOGGER = LyciaLoggerWrapper
			.getLogger(VisualAgeRPGTextReader.class);

	private LyciaParser<B> lyciaParser;

	@Override
	public LyciaParser<B> getXmlParser() {
		return lyciaParser;
	}

	@Override
	public Document read(InputSource inputSource) throws Exception {
		final DocumentBuilderFactory factory = DocumentBuilderFactory
				.newInstance();
		final DocumentBuilder documentBuilder = factory.newDocumentBuilder();
		final Document document = documentBuilder.newDocument();

		LineNumberReader reader = new LineNumberReader(inputSource
				.getCharacterStream());

		Element root = document.createElementNS("", "root");
		document.appendChild(root);

		recursiveRead(reader, root, document);

		return document;
	}

	@Override
	public void setXmlParser(LyciaParser<B> xmlParser) {
		this.lyciaParser = xmlParser;
	}

	private void recursiveRead(LineNumberReader reader, Element parent,
			Document document) throws IOException, LyciaParsingException {

		String line;
		while ((line = reader.readLine()) != null) {
			line = line.replace("\t", "").trim();

			if (line.startsWith("BEGIN_OBJECT")) {
				String[] data = readNameValue(line);
				LOGGER.debug("Found object " + data[1]);
				Element element = document.createElementNS("", data[1]);
				recursiveRead(reader, element, document);
				parent.appendChild(element);

			} else if (line.charAt(0) == '[') {
				String[] data = readNameValue(line);
				LOGGER.debug("Found attribute " + data[0] + " with value "
						+ data[1] + " on object " + parent.getNodeName());
				parent.setAttributeNS("", data[0], data[1]);

			} else if (line.startsWith("END_OBJECT")) {
				LOGGER.debug("Finished object " + parent.getNodeName());
				return;

			} else if (line.charAt(0) == '#') {
				continue;

			} else {
				String[] data = readNameValue(line);
				LOGGER.debug("Found value element " + data[0] + " with value "
						+ data[1] + " on object " + parent.getNodeName());
				Element element = document.createElementNS("", data[0]);
				Text text = document.createTextNode(data[1]);
				element.appendChild(text);
				parent.appendChild(element);
			}
		}
	}

	private String[] readNameValue(String line) throws LyciaParsingException {
		int pos = line.indexOf("=");
		if (pos == -1)
			throw new LyciaParsingException(
					"Illegal Attribute - missing value separator");

		String name = line.substring(0, pos);
		if (name.charAt(0) == '[')
			name = name.substring(1, name.length() - 1);

		String value = "";
		if (line.length() >= pos + 1)
			value = line.substring(pos + 1);

		return new String[] { name, value };
	}

}
